package by.dkusch.aircompany.dao.impl;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.metamodel.SingularAttribute;

import org.hibernate.jpa.criteria.OrderImpl;
import org.springframework.stereotype.Repository;

import by.dkusch.aircompany.dao.PlaneTypeDao;
import by.dkusch.aircompany.model.filter.FilterPlaneType;
import by.dkusch.aircompany.model.filter.base.FilterEntity;
import by.dkusch.aircompany.model.tables.Plane;
import by.dkusch.aircompany.model.tables.PlaneType;
import by.dkusch.aircompany.model.tables.PlaneType_;
import by.dkusch.aircompany.model.tables.Plane_;
import by.dkusch.aircompany.model.tables.base.BaseEntity_;

@Repository
public class PlaneTypeDaoImpl extends AbstractDaoImpl<Long, PlaneType> implements PlaneTypeDao {

	public PlaneTypeDaoImpl() {
		super(PlaneType.class);
	}

	@Override
	public List<PlaneType> getAllItemsWithFilter(SingularAttribute<? super PlaneType, ?> attr, boolean ascending, int startRecord, int pageSize, FilterEntity<Long, ? super PlaneType> filter) {
		if (filter == null) {
			return getAllItems(attr, ascending, startRecord, pageSize);
		}

		CriteriaBuilder cBuilder = getEm().getCriteriaBuilder();

		CriteriaQuery<PlaneType> criteria = cBuilder.createQuery(PlaneType.class);
		Root<PlaneType> fromPlaneType = criteria.from(PlaneType.class);

		OrderImpl order = new OrderImpl(fromPlaneType.get(BaseEntity_.id), ascending);
		if (attr != null) {
			order = new OrderImpl(fromPlaneType.get(attr), ascending);
		}
		;
		List<Predicate> conditions = new ArrayList<Predicate>();

		FilterPlaneType fc = (FilterPlaneType) filter;

		if (fc.getCode() != null) {
			conditions.add(cBuilder.equal(cBuilder.upper(fromPlaneType.get(PlaneType_.code)), fc.getCode().toUpperCase()));
		}

		if (fc.getName() != null) {
			conditions.add(cBuilder.like(cBuilder.upper(fromPlaneType.get(PlaneType_.name)), fc.getName().toUpperCase()));
		}

		if ((fc.getPassClass1Min() != null) || (fc.getPassClass1Max() != null)) {
			conditions.add(cBuilder.between(fromPlaneType.get(PlaneType_.passClass1), fc.getPassClass1Min() == null ? 0 : fc.getPassClass1Min(),
					fc.getPassClass1Max() == null ? Integer.MAX_VALUE : fc.getPassClass1Max()));
		}

		if ((fc.getPassClass2Min() != null) || (fc.getPassClass2Max() != null)) {
			conditions.add(cBuilder.between(fromPlaneType.get(PlaneType_.passClass2), fc.getPassClass2Min() == null ? 0 : fc.getPassClass2Min(),
					fc.getPassClass2Max() == null ? Integer.MAX_VALUE : fc.getPassClass2Max()));
		}

		if ((fc.getPassClass3Min() != null) || (fc.getPassClass3Max() != null)) {
			conditions.add(cBuilder.between(fromPlaneType.get(PlaneType_.passClass3), fc.getPassClass3Min() == null ? 0 : fc.getPassClass3Min(),
					fc.getPassClass3Max() == null ? Integer.MAX_VALUE : fc.getPassClass3Max()));
		}

		if ((fc.getCrewCountMax() != null) || (fc.getCrewCountMin() != null)) {
			conditions.add(cBuilder.between(fromPlaneType.get(PlaneType_.crewCount), fc.getCrewCountMin() == null ? 0 : fc.getCrewCountMin(),
					fc.getCrewCountMax() == null ? Integer.MAX_VALUE : fc.getCrewCountMax()));
		}

		if ((fc.getLengthMin() != null) || (fc.getLengthMax() != null)) {
			conditions.add(cBuilder.between(fromPlaneType.get(PlaneType_.length), fc.getLengthMin() == null ? 0.0 : fc.getLengthMin(),
					fc.getLengthMax() == null ? new Double(Integer.MAX_VALUE) : fc.getLengthMax()));
		}

		if ((fc.getWeightMin() != null) || (fc.getWeightMax() != null)) {
			conditions.add(cBuilder.between(fromPlaneType.get(PlaneType_.weight), fc.getWeightMin() == null ? 0.0 : fc.getWeightMin(),
					fc.getWeightMax() == null ? new Double(Integer.MAX_VALUE) : fc.getWeightMax()));
		}

		TypedQuery<PlaneType> query = getEm().createQuery(criteria.select(fromPlaneType).where(cBuilder.and(conditions.toArray(new Predicate[] {}))).orderBy(order));

		if (startRecord >= 0) {
			query.setFirstResult(startRecord);
			query.setMaxResults(pageSize);
		}

		List<PlaneType> results = query.getResultList();
		return results;

	}

	@Override
	public boolean checkCanRemoveRecord(PlaneType entity) {
		CriteriaBuilder cBuilder = getEm().getCriteriaBuilder();
		CriteriaQuery<Plane> criteria = cBuilder.createQuery(Plane.class);

		Root<Plane> fromPlane = criteria.from(Plane.class);
		Join<Plane, PlaneType> fromPlaneType = fromPlane.join(Plane_.planeType);

		List<Predicate> conditions = new ArrayList<Predicate>();
		conditions.add(cBuilder.equal(fromPlaneType.get(PlaneType_.id), entity.getId()));

		TypedQuery<Plane> query = getEm().createQuery(criteria.select(fromPlane).where(cBuilder.and(conditions.toArray(new Predicate[] {}))));
		List<Plane> results = query.getResultList();
		return (results == null) || ((results != null) && (results.size() == 0));
	}

}
